use std::rc::{Rc, Weak};
use std::cell::RefCell;

use crate::chess::{PieceColor, PointState, Point, Edge, ChessState};
use crate::chess::player::Player;


#[derive(Debug)]
pub struct Point {
    id: u8,
    piece: Option<PointState>,
    v: RefCell<Weak<Edge>>,
    h: RefCell<Weak<Edge>>,
}

impl Point {
    pub fn new(id: u8) -> Point {
        Point{
            id,
            piece: None,
            h: RefCell::new(Weak::new()),
            v: RefCell::new(Weak::new()),
        }
    }

    pub fn init_edge(&self, h: Rc<Edge>, v: Rc<Edge>) {
        *self.h.borrow_mut() = Rc::downgrade(&h);
        *self.v.borrow_mut() = Rc::downgrade(&v);
    }
}

#[derive(Debug)]
pub struct Edge {
    left: Rc<Point>,
    right: Rc<Point>,
    center: Rc<Point>,
}

impl Edge {
    pub fn new(left: Rc<Point>, center: Rc<Point>, right: Rc<Point>) -> Edge {
        Edge {
            left,
            right,
            center
        }
    }
}

pub struct Chessboard {
    state: ChessState,
    points: Vec<Rc<Point>>,
    lines: Vec<Rc<Edge>>,
    current: RefCell<Player>,
    opponent: RefCell<Player>,
}

impl Chessboard {
    pub fn new() -> Chessboard {
        let mut p0 = Rc::new(Point::new(0u8));
        let mut p1 = Rc::new(Point::new(1u8));
        let mut p2 = Rc::new(Point::new(2u8));
        let mut p3 = Rc::new(Point::new(3u8));
        let mut p4 = Rc::new(Point::new(4u8));
        let mut p5 = Rc::new(Point::new(5u8));
        let mut p6 = Rc::new(Point::new(6u8));
        let mut p7 = Rc::new(Point::new(7u8));
        let mut p8 = Rc::new(Point::new(8u8));
        let mut p9 = Rc::new(Point::new(9u8));
        let mut p10 = Rc::new(Point::new(10u8));
        let mut p11 = Rc::new(Point::new(11u8));
        let mut p12 = Rc::new(Point::new(12u8));
        let mut p13 = Rc::new(Point::new(13u8));
        let mut p14 = Rc::new(Point::new(14u8));
        let mut p15 = Rc::new(Point::new(15u8));
        let mut p16 = Rc::new(Point::new(16u8));
        let mut p17 = Rc::new(Point::new(17u8));
        let mut p18 = Rc::new(Point::new(18u8));
        let mut p19 = Rc::new(Point::new(19u8));
        let mut p20 = Rc::new(Point::new(20u8));
        let mut p21 = Rc::new(Point::new(21u8));
        let mut p22 = Rc::new(Point::new(22u8));
        let mut p23 = Rc::new(Point::new(23u8));
        let mut p24 = Rc::new(Point::new(24u8));


        let l01 = Rc::new(Edge::new(p0.clone(), p1.clone(), p2.clone()));
        let l02 = Rc::new(Edge::new(p2.clone(), p3.clone(), p4.clone()));
        let l03 = Rc::new(Edge::new(p4.clone(), p5.clone(), p6.clone()));
        let l04 = Rc::new(Edge::new(p6.clone(), p7.clone(), p0.clone()));
        let l05 = Rc::new(Edge::new(p8.clone(), p9.clone(), p10.clone()));
        let l06 = Rc::new(Edge::new(p10.clone(), p11.clone(), p12.clone()));
        let l07 = Rc::new(Edge::new(p12.clone(), p13.clone(), p14.clone()));
        let l08 = Rc::new(Edge::new(p14.clone(), p15.clone(), p8.clone()));
        let l09 = Rc::new(Edge::new(p16.clone(), p17.clone(), p18.clone()));
        let l10 = Rc::new(Edge::new(p18.clone(), p19.clone(), p20.clone()));
        let l11 = Rc::new(Edge::new(p20.clone(), p21.clone(), p22.clone()));
        let l12 = Rc::new(Edge::new(p22.clone(), p23.clone(), p16.clone()));
        let l13 = Rc::new(Edge::new(p1.clone(), p9.clone(), p17.clone()));
        let l14 = Rc::new(Edge::new(p3.clone(), p11.clone(), p19.clone()));
        let l15 = Rc::new(Edge::new(p5.clone(), p13.clone(), p21.clone()));
        let l16 = Rc::new(Edge::new(p7.clone(), p15.clone(), p23.clone()));


        p0.init_edge(l01.clone(), l04.clone());
        p1.init_edge(l01.clone(), l13.clone());
        p2.init_edge(l01.clone(), l02.clone());
        p3.init_edge(l02.clone(), l14.clone());
        p4.init_edge(l02.clone(), l03.clone());
        p5.init_edge(l03.clone(), l15.clone());
        p6.init_edge(l03.clone(), l04.clone());
        p7.init_edge(l04.clone(), l16.clone());
        p8.init_edge(l05.clone(), l08.clone());
        p9.init_edge(l05.clone(), l13.clone());
        p10.init_edge(l06.clone(), l05.clone());
        p11.init_edge(l06.clone(), l14.clone());
        p12.init_edge(l07.clone(), l06.clone());
        p13.init_edge(l07.clone(), l15.clone());
        p14.init_edge(l08.clone(), l07.clone());
        p15.init_edge(l08.clone(), l16.clone());
        p16.init_edge(l09.clone(), l12.clone());
        p17.init_edge(l09.clone(), l13.clone());
        p18.init_edge(l10.clone(), l09.clone());
        p19.init_edge(l10.clone(), l14.clone());
        p20.init_edge(l11.clone(), l10.clone());
        p21.init_edge(l11.clone(), l15.clone());
        p22.init_edge(l12.clone(), l11.clone());
        p23.init_edge(l12.clone(), l16.clone());

        Chessboard{
            state: ChessState::Put,
            points: vec![p0.clone(),
                         p1.clone(),
                         p2.clone(),
                         p3.clone(),
                         p4.clone(),
                         p5.clone(),
                         p6.clone(),
                         p7.clone(),
                         p8.clone(),
                         p9.clone(),
                         p10.clone(),
                         p11.clone(),
                         p12.clone(),
                         p13.clone(),
                         p14.clone(),
                         p15.clone(),
                         p16.clone(),
                         p17.clone(),
                         p18.clone(),
                         p19.clone(),
                         p20.clone(),
                         p21.clone(),
                         p22.clone(),
                         p23.clone(),
                         p24.clone(),],
            lines: vec![l01.clone(),
                        l02.clone(),
                        l03.clone(),
                        l04.clone(),
                        l05.clone(),
                        l06.clone(),
                        l07.clone(),
                        l08.clone(),
                        l09.clone(),
                        l10.clone(),
                        l11.clone(),
                        l12.clone(),
                        l13.clone(),
                        l14.clone(),
                        l15.clone(),
                        l16.clone()],
            current: RefCell::new(Player::new(PieceColor::Black)),
            opponent: RefCell::new(Player::new(PieceColor::White)),
        }
    }
}